#include "Audio.h"
#include "app_common.h"
#include "mad.h"
#include "hi_mw_media_intf.h"
#include "adpt_acap_acodec.h"
#include "g711.h"

typedef struct tagAUDIO_PLAY_FILE
{
    pthread_t pid_audio_play;
    int flag_audio_play;
    AUDIO_ENCODE_TYPE_E type;
    char loop;
    char AudioFileName[255];
    char bPause;
    char bForce;
}HISI_LITEOS_AUDIO_PLAY_FILE;

static HISI_LITEOS_AUDIO_PLAY_FILE g_audio_play_file;
static AudioAencDataCallback gs_pfnLiteosAencDataCb[AUDIO_AENC_CHN_MAX_NUM];

#define HI_AO_VOLUME 80

typedef struct {
    char bInited;
}HISI_LITEOS_AUDIO_CONTEXT_S;

HISI_LITEOS_AUDIO_CONTEXT_S g_hisiLiteosAudioCtx = {
    .bInited = 0,
};

HISI_LITEOS_AUDIO_CONTEXT_S *hisi_liteos_audio_get_ctx(void)
{
    return &g_hisiLiteosAudioCtx;
}

int hisi_liteos_audio_init(void)
{
    int ret = 0;
    HISI_LITEOS_AUDIO_CONTEXT_S *ctx = hisi_liteos_audio_get_ctx();
    
    memset(&g_audio_play_file, 0, sizeof(g_audio_play_file));

    ret = HalAudioAiInit();
    if (ret < 0) {
        LOGE("HalAudioAiInit failed\n");
        return -1;
    }
    
    ret = HalAudioAoInit();
    if (ret < 0) {
        LOGE("HalAudioAoInit failed\n");
        return -1;
    }
    
    ctx->bInited = 1;
    
    return 0;
}


int hisi_liteos_audio_deinit(void)
{
    int ret = 0;
    HISI_LITEOS_AUDIO_CONTEXT_S *ctx = hisi_liteos_audio_get_ctx();

    if (ctx->bInited) 
    {
        ctx->bInited = 0;
        ret = HalAudioAiDeinit();
        if (ret < 0) {
            LOGE("HalAudioAiDeinit failed\n");
            return -1;
        }
        
        ret = HalAudioAoDeinit();
        if (ret < 0) {
            LOGE("HalAudioAoDeinit failed\n");
            return -1;
        }
    }
    
    return 0;
}

static signed short to_short(mad_fixed_t fixed)
{
    if (fixed >= MAD_F_ONE) {
        return (SHRT_MAX);
    }
    if (fixed <= -MAD_F_ONE) {
        return (-SHRT_MAX);
    }
    fixed = fixed >> (MAD_F_FRACBITS - 15);
    return ((signed short)fixed);
}

static unsigned int gs_playTaskid;

static void task_play_audio(void)
{
    int iRet;
    FILE *fp = NULL;
    int read_bytes = 0;
    HISI_LITEOS_AUDIO_PLAY_FILE *audio_play_file = &g_audio_play_file;
    unsigned char mp3buf[4096 + MAD_BUFFER_GUARD];
    int firstSetAudioOut = 1;
    int numperframe = 480 * 2;

    GpioSet(PRODUCT_GPIO_SPEAK_ENABLE);

    /* different playback modules set the volume differently */
    PLAY_VOLUME_CONFIG stPlayVol;
    hisi_liteos_audio_get_play_volume(&stPlayVol);
    
	if (strcmp(audio_play_file->AudioFileName, AUDIO_ALARM) == 0) {
        hisi_liteos_audio_set_ao_volume(stPlayVol.alarmVol);
	} else {
        hisi_liteos_audio_set_ao_volume(stPlayVol.netcfgVol);
	}
	
    LOGI("AudioPlayFileTask %s,%d,%d\n", audio_play_file->AudioFileName, audio_play_file->type, audio_play_file->loop);
    fp = fopen(audio_play_file->AudioFileName, "r");	
    if(fp == NULL) {
        perror("fopen");
        goto err_return;
    } else {
         fseek(fp, 0L, SEEK_SET);
    }

    usleep(500 * 1000);
    
    switch(audio_play_file->type)
    {
        case AUDIO_TYPE_G711A:
        case AUDIO_TYPE_G711U:
            break;   
        case AUDIO_TYPE_MP3:
            {
                struct mad_stream   stream;
                struct mad_frame    frame;
                struct mad_synth    synth;
                unsigned int        remaining = 0;
                unsigned char       *mp3BufTmp = NULL;
                unsigned char       pcm[4096];
                int i=0, j=0, remain=0;
                
                mad_stream_init(&stream);
                mad_frame_init(&frame);
                mad_synth_init(&synth);
      
                while (audio_play_file->flag_audio_play) 
				{
                    if ((stream.error == MAD_ERROR_BUFLEN) || ((stream.buffer == NULL) && !MAD_RECOVERABLE(stream.error))) 
					{
                        if (stream.next_frame != NULL) {
                            remaining=stream.bufend-stream.next_frame;
                            memmove(mp3buf, stream.next_frame, remaining);
                            mp3BufTmp = mp3buf + remaining;
                            read_bytes = (sizeof(mp3buf) - MAD_BUFFER_GUARD) - remaining;
                        } else {
                            read_bytes = (sizeof(mp3buf) - MAD_BUFFER_GUARD);
                            mp3BufTmp = mp3buf;
                            remaining = 0;
                        }
                        
                        read_bytes = fread(mp3BufTmp, sizeof(mp3BufTmp[0]), read_bytes, fp);			
                        if (read_bytes <= 0) 
						{
                            if (audio_play_file->loop) 
							{
                                if (0 == access(audio_play_file->AudioFileName, R_OK)) 
								{
                                    iRet = fseek(fp, 0, SEEK_SET);
                                    if (iRet != 0) {
                                        LOGE("fseek file(%s) error\n", audio_play_file->AudioFileName);
                                        break;
                                    }
                                } 
								else 
                                {
                                    LOGE("access file(%s) R_OK error\n", audio_play_file->AudioFileName);
                                    break;
                                }
                            } 
							else 
							{
                                //printf("fread %s error(%d)\n", audio_play_file->AudioFileName, read_bytes);
                                break;
                            }
                        }
                        mad_stream_buffer(&stream, mp3buf, (read_bytes + remaining));
                        stream.error=(enum mad_error)0;
                    }
                    
                    if (0 != mad_frame_decode(&frame, &stream))
					{
                        if (MAD_RECOVERABLE(stream.error)) {
                            continue;
                        } else if (stream.error == MAD_ERROR_BUFLEN) {
                            continue;
                        } else {
                            LOGE("mad_frame_decode error\n");
                            break;
                        }
                    }

                    mad_synth_frame(&synth,&frame);
                    if (firstSetAudioOut) 
                    {                  
                        //audio_out_init();          
                        firstSetAudioOut = 0;
                    }
                    for (i = 0, j=remain; i < synth.pcm.length; i++) 
                    {
                        signed short    sample;
                        sample = to_short(synth.pcm.samples[0][i]); 
                        pcm[j++] = sample & 0xff;
                        pcm[j++] = sample >> 8;
                    }
                    remain = j;
                    i = 0;			
					
                    while (remain > numperframe)
                    {
                        int iRet = -1;

                        iRet = HalAudioAoSendFrame(pcm+(i*numperframe), numperframe);
                        if (iRet < 0) {
                            LOGE("HalAudioAoSendFrame failed\n");
                            goto err_return;
                        }
                        i++;
                        remain -= numperframe;
                        usleep(25*1000);
                        ////////////////////////////////////
                        if (audio_play_file->bPause == 1)
                        {
                            LOGI("MP3 PLAY PAUSE!!!!\n\n");
                            while(1)
                            {
                            	if (audio_play_file->bPause == 0 || audio_play_file->flag_audio_play == 0)
                            	{
                            		audio_play_file->bPause = 0; 
                            		break;
                            	}
                            	usleep(10*1000);
                            }
                        }      
                        ////////////////////////////////////
                    }					
                    memmove(pcm, pcm + (i * numperframe), remain);
                }//end_while(1)             		 
                mad_synth_finish(&synth);
                mad_frame_finish(&frame);
                mad_stream_finish(&stream);
                
                break;
            }
        default:
            LOGW("not support type %d\n", audio_play_file->type);
            break;
    }
    fclose(fp);
    
#ifdef YD_PROTOCOL
    usleep(1000 * 1000);
#else
    usleep(2000 * 1000);
#endif /* YD_PROTOCOL */

	if (audio_play_file->flag_audio_play == 1) {
	    HI_MPI_AO_ClearChnBuf(0, 0);
	}

err_return:
    audio_play_file->flag_audio_play = 0;
    audio_play_file->bForce = 0;
    GpioReset(PRODUCT_GPIO_SPEAK_ENABLE);

    iRet = LOS_TaskDelete(gs_playTaskid);
    if (0 != iRet)
    {
        LOGE("%s[%d]:delete task fail[%d]",__func__,__LINE__,iRet);
    }
    gs_playTaskid = 0;
}

static int onPlayAudioFile(void)
{
    unsigned int        ul_ret;
    int                 l_ret;
    unsigned char       uc_status;
    TSK_INIT_PARAM_S    st_hsl_task;

    gs_playTaskid = 0;
   /* 创建切信道线程,线程结束后自动释放 */
    memset(&st_hsl_task, 0, sizeof(TSK_INIT_PARAM_S));
    st_hsl_task.pfnTaskEntry = (TSK_ENTRY_FUNC)task_play_audio;

    //st_hsl_task.uwStackSize  = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
    st_hsl_task.uwStackSize  = 0x10000;
    st_hsl_task.pcName       = "onPlayAudioFile";
    st_hsl_task.usTaskPrio   = 10;
    st_hsl_task.uwResved     = LOS_TASK_STATUS_DETACHED;
    ul_ret = LOS_TaskCreate(&gs_playTaskid, &st_hsl_task);
    if(0 != ul_ret){
       LOGE("%s[%d]:create task fail[%d]",__func__,__LINE__,ul_ret);
       return -1;
    }
    
    return 0;
}

static void *tskAudioPlayFile(void *args)
{
    SET_THREAD_NAME("tskAudioPlayFile");
    pthread_detach(pthread_self());

    int iRet = 0;;
    FILE *fp = NULL;
    int read_bytes = 0;
    HISI_LITEOS_AUDIO_PLAY_FILE *audio_play_file = (HISI_LITEOS_AUDIO_PLAY_FILE *)args;
    unsigned char mp3buf[4096 + MAD_BUFFER_GUARD] = {0};
    int firstSetAudioOut = 1;
    int numperframe = 480 * 2;
    
    GpioSet(PRODUCT_GPIO_SPEAK_ENABLE);

    /* different playback modules set the volume differently */
    PLAY_VOLUME_CONFIG stPlayVol;
    hisi_liteos_audio_get_play_volume(&stPlayVol);
    
	if (strcmp(audio_play_file->AudioFileName, AUDIO_ALARM) == 0) {
        hisi_liteos_audio_set_ao_volume(stPlayVol.alarmVol);
	} else {
        hisi_liteos_audio_set_ao_volume(stPlayVol.netcfgVol);
	}

    LOGI("AudioPlayFileTask %s,%d,%d\n", audio_play_file->AudioFileName, audio_play_file->type, audio_play_file->loop);
    fp = fopen(audio_play_file->AudioFileName, "r");	
    if(fp == NULL) {
        audio_play_file->flag_audio_play = 0;
        GpioReset(PRODUCT_GPIO_SPEAK_ENABLE);
        perror("fopen");
        return NULL;
    } else {
         fseek(fp, 0L, SEEK_SET);
    }

    usleep(500 * 1000);
    
    switch(audio_play_file->type)
    {
        case AUDIO_TYPE_G711A:
        case AUDIO_TYPE_G711U:
            break;   
        case AUDIO_TYPE_MP3:
            {
                struct mad_stream   stream;
                struct mad_frame    frame;
                struct mad_synth    synth;
                unsigned int        remaining = 0;
                unsigned char       *mp3BufTmp = NULL;
                unsigned char       pcm[4096];
                int i=0, j=0, remain=0;
                
                mad_stream_init(&stream);
                mad_frame_init(&frame);
                mad_synth_init(&synth);
      
                while (audio_play_file->flag_audio_play) 
				{
                    if ((stream.error == MAD_ERROR_BUFLEN) || ((stream.buffer == NULL) && !MAD_RECOVERABLE(stream.error))) 
					{
                        if (stream.next_frame != NULL) {
                            remaining=stream.bufend-stream.next_frame;
                            memmove(mp3buf, stream.next_frame, remaining);
                            mp3BufTmp = mp3buf + remaining;
                            read_bytes = (sizeof(mp3buf) - MAD_BUFFER_GUARD) - remaining;
                        } else {
                            read_bytes = (sizeof(mp3buf) - MAD_BUFFER_GUARD);
                            mp3BufTmp = mp3buf;
                            remaining = 0;
                        }
                        
                        read_bytes = fread(mp3BufTmp, sizeof(mp3BufTmp[0]), read_bytes, fp);			
                        if (read_bytes <= 0) 
						{
                            if (audio_play_file->loop) 
							{
                                if (0 == access(audio_play_file->AudioFileName, R_OK)) 
								{
                                    iRet = fseek(fp, 0, SEEK_SET);
                                    if (iRet != 0) {
                                        LOGE("fseek file(%s) error\n", audio_play_file->AudioFileName);
                                        break;
                                    }
                                } 
								else 
                                {
                                    LOGE("access file(%s) R_OK error\n", audio_play_file->AudioFileName);
                                    break;
                                }
                            } 
							else 
							{
                                //printf("fread %s error(%d)\n", audio_play_file->AudioFileName, read_bytes);
                                break;
                            }
                        }
                        mad_stream_buffer(&stream, mp3buf, (read_bytes + remaining));
                        stream.error=(enum mad_error)0;
                    }
                    
                    if (0 != mad_frame_decode(&frame, &stream))
					{
                        if (MAD_RECOVERABLE(stream.error)) {
                            continue;
                        } else if (stream.error == MAD_ERROR_BUFLEN) {
                            continue;
                        } else {
                            LOGE("mad_frame_decode error\n");
                            break;
                        }
                    }

                    mad_synth_frame(&synth,&frame);
                    if (firstSetAudioOut) 
                    {                  
                        firstSetAudioOut = 0;
                    }
                    for (i = 0, j=remain; i < synth.pcm.length; i++) 
                    {
                        signed short    sample;
                        sample = to_short(synth.pcm.samples[0][i]); 
                        pcm[j++] = sample & 0xff;
                        pcm[j++] = sample >> 8;
                    }
                    remain = j;
                    i = 0;			
					
                    while (remain > numperframe)
                    {
                        int iRet = -1;

                        iRet = HalAudioAoSendFrame(pcm+(i*numperframe), numperframe);
                        if (iRet < 0) {
                            LOGE("HalAudioAoSendFrame failed\n");
                            return NULL;
                        }
                        i++;
                        remain -= numperframe;
                        usleep(25*1000);
                        ////////////////////////////////////
                        if (audio_play_file->bPause == 1)
                        {
                            LOGI("MP3 PLAY PAUSE!!!!\n\n");
                            while(1)
                            {
                            	if (audio_play_file->bPause == 0 || audio_play_file->flag_audio_play == 0)
                            	{
                            		audio_play_file->bPause = 0; 
                            		break;
                            	}
                            	usleep(10*1000);
                            }
                        }      
                        ////////////////////////////////////
                    }					
                    memmove(pcm, pcm + (i * numperframe), remain);
                }//end_while(1)             		 
                mad_synth_finish(&synth);
                mad_frame_finish(&frame);
                mad_stream_finish(&stream);
                
                break;
            }
        default:
            LOGW("not support type %d\n", audio_play_file->type);
            break;
    }
    fclose(fp);

#ifdef YD_PROTOCOL
    usleep(1000 * 1000);
#else
    usleep(2000 * 1000);
#endif /* YD_PROTOCOL */
	if (audio_play_file->flag_audio_play == 1)
	{
		HI_MPI_AO_ClearChnBuf(0, 0);
	}

    audio_play_file->flag_audio_play = 0;
    audio_play_file->bForce = 0;
   
    GpioReset(PRODUCT_GPIO_SPEAK_ENABLE);

    pthread_exit(0);
}

int hisi_liteos_audio_play_file_start(char *audioFile, AUDIO_ENCODE_TYPE_E enAudioType, char bLoop)
{
#ifdef MINI_APP
        return 0;
#endif /* MINI_APP */

    HISI_LITEOS_AUDIO_CONTEXT_S *ctx = hisi_liteos_audio_get_ctx();
    
    if (0 == ProductGetHandle()->bAudio) {
        return 0;
    }

    if (!ctx->bInited) {
        LOGW("audio don't init\n");
        return -1;
    }
    
    if(1 == g_audio_play_file.flag_audio_play)
    {
        LOGW("audio already in play\n");
        return -1;
    }
    else
    {
    	g_audio_play_file.flag_audio_play = 1;
        memset(g_audio_play_file.AudioFileName, 0, sizeof(g_audio_play_file.AudioFileName));
        strcpy(g_audio_play_file.AudioFileName, audioFile);
        g_audio_play_file.type = enAudioType;
        g_audio_play_file.loop = bLoop;
        
        LOGD("AudioPlayAudioStart running \n");
#if 0
        pthread_attr_t attr;
        pthread_attr_setstacksize(&attr, 1024 * 64);
        if(0 != pthread_create(&g_audio_play_file.pid_audio_play, &attr, tskAudioPlayFile, (void*)&g_audio_play_file))
		{
			g_audio_play_file.flag_audio_play = 0;
			return -1;
		}
		pthread_attr_destroy(&attr);
#else
        onPlayAudioFile();
#endif
    }    

    return 0;
}

int hisi_liteos_audio_play_file_stop(void)
{
    LOGD("test\n");
    return 0;
}

int hisi_liteos_audio_set_ao_volume(int volume)
{
#ifdef MINI_APP
    return 0;
#endif /* MINI_APP */

    int ret = 0;
    int convertVolume = 0;

    /* 限制音量最低可听范围阈值,经测试低于60已经听不到声音,因此限制在60以上 */
    convertVolume = 60 + 0.4 * volume;
    
    ret = ADPT_ACODEC_SetAOVol(convertVolume);
    if (ret < 0) {
        LOGE("ADPT_ACODEC_SetAOVol failed\n");
        return -1;
    }
    
    return 0;
}

int hisi_liteos_audio_set_play_volume(PLAY_VOLUME_CONFIG stPlayVol)
{
#if 0
    int ret = 0;
    
    ret = hisi_liteos_audio_set_ao_volume(volume);
    if (ret < 0) {
        LOGE("hisi_liteos_audio_set_ao_volume failed\n");
        return -1;
    }
#endif
    return DevConfigSetPlayVolume(stPlayVol);
}


int hisi_liteos_audio_get_play_volume(PLAY_VOLUME_CONFIG *pstPlayVol)
{
    return DevConfigGetPlayVolume(pstPlayVol);
}

int hisi_liteos_audio_talkback_start(void)
{
    LOGD("AudioTalkPlayStart\n");
    
    if (ProductGetHandle()->bAudio) {
        GpioSet(PRODUCT_GPIO_SPEAK_ENABLE);
        PLAY_VOLUME_CONFIG stPlayVol;
        hisi_liteos_audio_get_play_volume(&stPlayVol);

#ifndef YD_PROTOCOL
        /* 限制对讲音量最大为60 */
        if (stPlayVol.talkbackVol < HI_AO_VOLUME) {
            hisi_liteos_audio_set_ao_volume(stPlayVol.talkbackVol);
        } else {
            hisi_liteos_audio_set_ao_volume(HI_AO_VOLUME);
        }
#else
	#if 0
	/* 移动对接，将对讲音量化分为五个等级，限制对讲音量最大为80 */
	if (stPlayVol.talkbackVol > 60 && stPlayVol.talkbackVol <= 80)
		stPlayVol.talkbackVol = 70;
	else if (stPlayVol.talkbackVol > 80 && stPlayVol.talkbackVol < 100)
		stPlayVol.talkbackVol = 80;
	hisi_liteos_audio_set_ao_volume(stPlayVol.talkbackVol);
	#else
	/* 限制对讲音量最大为60 */
        if (stPlayVol.talkbackVol < HI_AO_VOLUME) {
            hisi_liteos_audio_set_ao_volume(stPlayVol.talkbackVol);
        } else {
            hisi_liteos_audio_set_ao_volume(HI_AO_VOLUME);
        }
	#endif
#endif
    }
    
    return 0;
}

int hisi_liteos_audio_talkback_data(unsigned char *pData, int nLen, AUDIO_ENCODE_TYPE_E enAudioType)
{
    LOGD("enAudioType:%d nLen:%d\n", enAudioType, nLen);
    
    int ret = 0;
    
    if (ProductGetHandle()->bAudio)
    {
        switch (enAudioType)
        {
            case AUDIO_TYPE_PCM:
                {
                    ret = HalAudioAoSendFrame(pData, nLen);
                    if (ret < 0) {
                        LOGE("HalAudioAoSendFrame failed\n");
                        return ret;
                    }
                }
                break;
            case AUDIO_TYPE_G711A:
                {
                    unsigned char *pcm = NULL;
					int pcmLen = 0;

                    if (nLen > 1024 || nLen < 0) {
                        LOGE("g711a len error %d\n", nLen);
                        return -1;
                    }

					pcm = (unsigned char *)malloc(2048);
					if (pcm == NULL) {
						LOGE("malloc failed\n");
						return -1;
					}

                   
                    g711_adec(pData, nLen, pcm, &pcmLen);
                    if (pcmLen <= 0) {
                        LOGE("g711_adec failed\n");
						free(pcm);
                        return -1;
                    }
                    
                    ret = HalAudioAoSendFrame(pcm, pcmLen);
                    if (ret < 0) {
                        LOGE("HalAudioAoSendFrame failed\n");
						free(pcm);
                        return ret;
                    }
					free(pcm);
                }
                break;
            case AUDIO_TYPE_G711U:
                {
                    unsigned char *pcm = NULL;
					int pcmLen = 0;

                    if (nLen > 1024 || nLen < 0) {
                        LOGE("g711u len error %d\n", nLen);
                        return -1;
                    }
                    
					pcm = (unsigned char *)malloc(2048);
					if (pcm == NULL) {
						LOGE("malloc failed\n");
						return -1;
					}

                    g711_udec(pData, nLen, pcm, &pcmLen);
                    if (pcmLen <= 0) {
                        LOGE("g711_udec failed\n");
						free(pcm);
                        return -1;
                    }
                    
                    ret = HalAudioAoSendFrame(pcm, pcmLen);
                    if (ret < 0) {
                        LOGE("HalAudioAoSendFrame failed\n");
						free(pcm);
                        return ret;
                    }
					free(pcm);
                }
                break;
            default:
                LOGW("enAudioType %d is invalid\n", enAudioType);
                break;
        }
    }

    return ret;
}

int hisi_liteos_audio_talkback_stop(void)
{
    LOGD("AudioTalkPlayStop\n");
    
    if (ProductGetHandle()->bAudio) 
    {
#ifndef YD_PROTOCOL
        GpioReset(PRODUCT_GPIO_SPEAK_ENABLE);
#endif
    }
    
    return 0;
}

static int OnHisiLiteosAencData(HI_HANDLE VencHdl, HI_MW_MEDIA_AUDIO_S* pVStreamData, HI_VOID* pPrivateData)
{
    int ret = 0;
    int chn = (int)VencHdl;

    if (NULL != gs_pfnLiteosAencDataCb[chn]) {
        ret = gs_pfnLiteosAencDataCb[chn](chn, (void *)pVStreamData);
    }

    return ret;
}

int hisi_liteos_audio_aenc_start(int chn, AudioAencDataCallback pfnAencDataCb)
{
    int ret = 0;

    gs_pfnLiteosAencDataCb[chn] = pfnAencDataCb;
    
    ret = HalAudioAencStart(chn, OnHisiLiteosAencData);
    if (ret < 0) {
        LOGE("HalAudioAencStart chn(%d) failed\n", chn);
        return -1;
    }

    return 0;
}

int hisi_liteos_audio_aenc_stop(int chn, AudioAencDataCallback pfnAencDataCb)
{
    int ret = 0;

    gs_pfnLiteosAencDataCb[chn] = NULL;
    
    ret = HalAudioAencStop(chn, OnHisiLiteosAencData);
    if (ret < 0) {
         LOGE("HalAudioAencStop chn(%d) failed\n", chn);
        return -1;
    }

    return 0;
}

int hisi_liteos_audio_copy_data(int chn, void *data, MEDIA_PACK_AUDIO *pstPackAudio, int maxSize)
{
    HI_MW_MEDIA_AUDIO_S *pVStreamData = (HI_MW_MEDIA_AUDIO_S *)data;

    pstPackAudio->stDataType.enEncType = MEDIA_ENC_TYPE_AAC;
    pstPackAudio->timestamp = pVStreamData->u64TimeStamp;
    pstPackAudio->frameSize = pVStreamData->u32Len;
    if (pVStreamData->u32Len > maxSize) {
        LOGE("u32Len (%d) more than maxSize (%d)!\n", pVStreamData->u32Len, maxSize);
        return -1;
    }
    memcpy(pstPackAudio->pFrameData, pVStreamData->pu8Addr, pVStreamData->u32Len);
    pstPackAudio->seq = pVStreamData->u32Seq;

    return 0;
}

static AUDIO_OPS_FUNC_S gs_stHisiLiteosAudioFuncOps = {
    .init                   = hisi_liteos_audio_init,
    .deinit                 = hisi_liteos_audio_deinit,
    
    .audio_aenc_start       = hisi_liteos_audio_aenc_start,
    .audio_aenc_stop         = hisi_liteos_audio_aenc_stop,

    .audio_copy_data        = hisi_liteos_audio_copy_data,
    
    .play_file_start        = hisi_liteos_audio_play_file_start,
    .play_file_stop         = hisi_liteos_audio_play_file_stop,

    .set_ao_volume          = hisi_liteos_audio_set_ao_volume,
    .set_play_volume        = hisi_liteos_audio_set_play_volume,
    .get_play_volume        = hisi_liteos_audio_get_play_volume,

    .talkback_start         = hisi_liteos_audio_talkback_start,
    .talkback_data          = hisi_liteos_audio_talkback_data,
    .talkback_stop          = hisi_liteos_audio_talkback_stop,
};

AUDIO_OPS_FUNC_S *hisi_liteos_audio_ops_handle(void)
{
	return &gs_stHisiLiteosAudioFuncOps;
}


